/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package client.process;

import com.sun.org.apache.xerces.internal.parsers.DOMParser;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

/**
 *
 * @author ifan
 */
public class XMLHandler {

    private ArrayList<File> arrayDir;
    private ArrayList<File> arrayFile;
    private String userXMLPath = "D:/kurakura/user.xml";

    private void addToArrayFileDir(String path) {
        ArrayList<File> files = new ArrayList<File>();
        ArrayList<File> dirs = new ArrayList<File>();
        files = GlobalProcess.getListFile(path);
        dirs = GlobalProcess.getListDir(path);
        int i;
        for(i=0;i<dirs.size();++i) {
            arrayDir.add(dirs.get(i));
        }
        for(i=0;i<files.size();++i) {
            arrayFile.add(files.get(i));
        }
    }

    private void inspectDirectory(String path) {
        ArrayList<File> dirs = new ArrayList<File>();
        dirs = GlobalProcess.getListDir(path);
        addToArrayFileDir(path);
        int i;
        for(i=0;i<dirs.size();++i){
            inspectDirectory(dirs.get(i).getAbsolutePath());
        }
    }

    public void updateInfoUsertoXML(HashMap<String, InfoUser> hashUser) {
        try {
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

            //root elements
            Document doc = docBuilder.newDocument();
            Element rootElement = doc.createElement("kurakura");
            doc.appendChild(rootElement);
            
            for(String s:hashUser.keySet()) {
                // user elements
                Element user = doc.createElement("user");
                rootElement.appendChild(user);

                // username element
                Element username = doc.createElement("username");
                username.appendChild(doc.createTextNode(s));
                user.appendChild(username);
                // repository element
                Element repository = doc.createElement("repository");
                repository.appendChild(doc.createTextNode(hashUser.get(s).repositoryPath));
                user.appendChild(repository);
                // interval element
                Element interval = doc.createElement("interval");
                interval.appendChild(doc.createTextNode(Integer.toString(hashUser.get(s).interval)));
                user.appendChild(interval);
            }

            //write the content into xml file
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource source = new DOMSource(doc);
            StreamResult result =  new StreamResult(new File(userXMLPath));
            transformer.transform(source, result);

            System.out.println("Done");
        }
        catch(ParserConfigurationException pce){
            pce.printStackTrace();
        }
        catch(TransformerException tfe){
            tfe.printStackTrace();
        }
    }

    public HashMap<String, InfoUser> readXMLUserToHash(String xmlPath) {
        HashMap<String, InfoUser> hashUser = new HashMap<String, InfoUser>();
        try {
            File file = new File(xmlPath);
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(file);
            doc.getDocumentElement().normalize();

            // hash user
            NodeList userList = doc.getElementsByTagName("user");
            int i;
            for(i=0;i<userList.getLength();++i) {
                Node user = userList.item(i);
                if(user.getNodeType() == user.ELEMENT_NODE) {
                    Element userElement = (Element) user;
                    // username
                    NodeList usernameList = userElement.getElementsByTagName("username");
                    Element usernameElement = (Element) usernameList.item(0);
                    NodeList username = usernameElement.getChildNodes();
                    String usernameS = ((Node) username.item(0)).getNodeValue();
                    // repository
                    NodeList repositoryList = userElement.getElementsByTagName("repository");
                    Element repositoryElement = (Element) repositoryList.item(0);
                    NodeList repository = repositoryElement.getChildNodes();
                    String repositoryS = ((Node) repository.item(0)).getNodeValue();
                    // interval
                    NodeList intervalList = userElement.getElementsByTagName("interval");
                    Element intervalElement = (Element) intervalList.item(0);
                    NodeList interval = intervalElement.getChildNodes();
                    String intervalS = ((Node) interval.item(0)).getNodeValue();
                    // hash
                    InfoUser info = new InfoUser();
                    info.interval = Integer.parseInt(intervalS);
                    info.repositoryPath = repositoryS;
                    hashUser.put(usernameS, info);
                }
            }
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
        return hashUser;
    }

    public void updateInfoPathToXML(String path) {
        arrayDir = new ArrayList<File>();
        arrayFile = new ArrayList<File>();
        inspectDirectory(path);
        try {
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

            //root elements
            Document doc = docBuilder.newDocument();
            Element rootElement = doc.createElement("kurakura");
            doc.appendChild(rootElement);

            // version elements
            Element version = doc.createElement("version");
            version.appendChild(doc.createTextNode(Integer.toString(GlobalVar.clientVersion)));
            rootElement.appendChild(version);

            // num_dir elements
            Element numDir = doc.createElement("num_dir");
            numDir.appendChild(doc.createTextNode(Integer.toString(arrayDir.size())));
            rootElement.appendChild(numDir);

            // num_file elements
            Element numFile = doc.createElement("num_file");
            numFile.appendChild(doc.createTextNode(Integer.toString(arrayFile.size())));
            rootElement.appendChild(numFile);

            int i;
            // directories elements
            Element directories = doc.createElement("directories");
            rootElement.appendChild(directories);
            int lengthPath = path.length();
            // directory element
            for(i=0;i<arrayDir.size();++i) {
                File dir = arrayDir.get(i);

                Element directory = doc.createElement("directory");
                directories.appendChild(directory);
                // absolut_path element
                Element absolutPath = doc.createElement("path");
                absolutPath.appendChild(doc.createTextNode(dir.getAbsolutePath().substring(lengthPath)));
                directory.appendChild(absolutPath);
                // timestamp element
                Element timestamp = doc.createElement("timestamp");
                timestamp.appendChild(doc.createTextNode(Long.toString(dir.lastModified())));
                directory.appendChild(timestamp);
            }

            // files elements
            Element files = doc.createElement("files");
            rootElement.appendChild(files);
//
            // file element
            for(i=0;i<arrayFile.size();++i) {
                File f = arrayFile.get(i);

                Element file = doc.createElement("file");
                files.appendChild(file);
                // absolut_path element
                Element absolutPath = doc.createElement("path");
                absolutPath.appendChild(doc.createTextNode(f.getAbsolutePath().substring(lengthPath)));
                file.appendChild(absolutPath);
                // timestamp element
                Element timestamp = doc.createElement("timestamp");
                timestamp.appendChild(doc.createTextNode(Long.toString(f.lastModified())));
                file.appendChild(timestamp);
            }

            //write the content into xml file
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource source = new DOMSource(doc);
            StreamResult result =  new StreamResult(new File(path+"/kur.xml"));
            transformer.transform(source, result);

            System.out.println("Done");
        }
        catch(ParserConfigurationException pce){
            pce.printStackTrace();
        }
        catch(TransformerException tfe){
            tfe.printStackTrace();
        }
    }

    public HashMap<String, InfoFile> readXMLToHash(String xmlPath) {
        HashMap<String, InfoFile> hashRepo = new HashMap<String, InfoFile>();
        try {
            File file = new File(xmlPath);
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(file);
            doc.getDocumentElement().normalize();

            // get revision
            NodeList nodeList= doc.getElementsByTagName("version");
            Node node = nodeList.item(0);
            if(node.getNodeType() == node.ELEMENT_NODE) {
                Element element = (Element) node;
                NodeList version = element.getChildNodes();
                System.out.println(version.item(0).getNodeValue());
                GlobalVar.clientVersion = Integer.parseInt(version.item(0).getNodeValue());
            }
            // get number dir
            nodeList = doc.getElementsByTagName("num_dir");
            node = nodeList.item(0);
            if(node.getNodeType() == node.ELEMENT_NODE) {
                Element element = (Element) node;
                NodeList numDir = element.getChildNodes();
                System.out.println(numDir.item(0).getNodeValue());
            }
            //get number file
            nodeList = doc.getElementsByTagName("num_file");
            node = nodeList.item(0);
            if(node.getNodeType() == node.ELEMENT_NODE) {
                Element element = (Element) node;
                NodeList numFile = element.getChildNodes();
                System.out.println(numFile.item(0).getNodeValue());
            }

            // hash directory
            nodeList = doc.getElementsByTagName("directories");
            node = nodeList.item(0);
            int i;
            if(node.getNodeType() == node.ELEMENT_NODE) {
                Element element = (Element) node;
                NodeList dirList = element.getElementsByTagName("directory");
                for(i=0;i<dirList.getLength();++i) {
                    Node dir = dirList.item(i);
                    if(dir.getNodeType() == node.ELEMENT_NODE) {
                        Element dirElement = (Element) dir;
                        //path
                        NodeList dirPathList = dirElement.getElementsByTagName("path");
                        Element dirPathElement = (Element) dirPathList.item(0);
                        NodeList dirPath = dirPathElement.getChildNodes();
                        String path = ((Node) dirPath.item(0)).getNodeValue();
                        //timestamp
                        NodeList dirTimeList = dirElement.getElementsByTagName("timestamp");
                        Element dirTimeElement = (Element) dirTimeList.item(0);
                        NodeList dirTime = dirTimeElement.getChildNodes();
                        Long timestamp = Long.parseLong(((Node) dirTime.item(0)).getNodeValue());
                        // hash path, timestamp
                        InfoFile info = new InfoFile();
                        info.timestamp = timestamp;
                        info.type = 0;
                        hashRepo.put(path, info);
                    }
                }
            }

            // hash file
            nodeList = doc.getElementsByTagName("files");
            node = nodeList.item(0);
            if(node.getNodeType() == node.ELEMENT_NODE) {
                Element element = (Element) node;
                NodeList fileList = element.getElementsByTagName("file");
                for(i=0;i<fileList.getLength();++i) {
                    Node f = fileList.item(i);
                    if(f.getNodeType() == node.ELEMENT_NODE) {
                        Element fileElement = (Element) f;
                        //path
                        NodeList filePathList = fileElement.getElementsByTagName("path");
                        Element filePathElement = (Element) filePathList.item(0);
                        NodeList filePath = filePathElement.getChildNodes();
                        String path = ((Node) filePath.item(0)).getNodeValue();
                        //timestamp
                        NodeList fileTimeList = fileElement.getElementsByTagName("timestamp");
                        Element fileTimeElement = (Element) fileTimeList.item(0);
                        NodeList fileTime = fileTimeElement.getChildNodes();
                        Long timestamp = Long.parseLong(((Node) fileTime.item(0)).getNodeValue());
                        // hash path, timestamp
                        InfoFile info = new InfoFile();
                        info.timestamp = timestamp;
                        info.type = 1;
                        hashRepo.put(path, info);
                    }
                }
            }
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
        return hashRepo;
    }

    public HashMap<String, InfoFile> stringXMLToHash(String xml) {
        HashMap<String, InfoFile> hashRepo = new HashMap<String, InfoFile>();
        try {
            DOMParser parser = new DOMParser();
            parser.parse(new InputSource(new java.io.StringReader(xml)));
            Document doc = parser.getDocument();
            doc.getDocumentElement().normalize();

            // get revision
            NodeList nodeList= doc.getElementsByTagName("version");
            Node node = nodeList.item(0);
            if(node.getNodeType() == node.ELEMENT_NODE) {
                Element element = (Element) node;
                NodeList version = element.getChildNodes();
                System.out.println(version.item(0).getNodeValue());
                GlobalVar.serverVersion = Integer.parseInt(version.item(0).getNodeValue());
            }
            // get number dir
            nodeList = doc.getElementsByTagName("num_dir");
            node = nodeList.item(0);
            if(node.getNodeType() == node.ELEMENT_NODE) {
                Element element = (Element) node;
                NodeList numDir = element.getChildNodes();
                System.out.println(numDir.item(0).getNodeValue());
            }
            //get number file
            nodeList = doc.getElementsByTagName("num_file");
            node = nodeList.item(0);
            if(node.getNodeType() == node.ELEMENT_NODE) {
                Element element = (Element) node;
                NodeList numFile = element.getChildNodes();
                System.out.println(numFile.item(0).getNodeValue());
            }

            // hash directory
            nodeList = doc.getElementsByTagName("directories");
            node = nodeList.item(0);
            int i;
            if(node.getNodeType() == node.ELEMENT_NODE) {
                Element element = (Element) node;
                NodeList dirList = element.getElementsByTagName("directory");
                for(i=0;i<dirList.getLength();++i) {
                    Node dir = dirList.item(i);
                    if(dir.getNodeType() == node.ELEMENT_NODE) {
                        Element dirElement = (Element) dir;
                        //path
                        NodeList dirPathList = dirElement.getElementsByTagName("path");
                        Element dirPathElement = (Element) dirPathList.item(0);
                        NodeList dirPath = dirPathElement.getChildNodes();
                        String path = ((Node) dirPath.item(0)).getNodeValue();
                        //timestamp
                        NodeList dirTimeList = dirElement.getElementsByTagName("timestamp");
                        Element dirTimeElement = (Element) dirTimeList.item(0);
                        NodeList dirTime = dirTimeElement.getChildNodes();
                        Long timestamp = Long.parseLong(((Node) dirTime.item(0)).getNodeValue());
                        // hash path, timestamp
                        InfoFile info = new InfoFile();
                        info.timestamp = timestamp;
                        info.type = 0;
                        hashRepo.put(path, info);
                    }
                }
            }

            // hash file
            nodeList = doc.getElementsByTagName("files");
            node = nodeList.item(0);
            if(node.getNodeType() == node.ELEMENT_NODE) {
                Element element = (Element) node;
                NodeList fileList = element.getElementsByTagName("file");
                for(i=0;i<fileList.getLength();++i) {
                    Node f = fileList.item(i);
                    if(f.getNodeType() == node.ELEMENT_NODE) {
                        Element fileElement = (Element) f;
                        //path
                        NodeList filePathList = fileElement.getElementsByTagName("path");
                        Element filePathElement = (Element) filePathList.item(0);
                        NodeList filePath = filePathElement.getChildNodes();
                        String path = ((Node) filePath.item(0)).getNodeValue();
                        //timestamp
                        NodeList fileTimeList = fileElement.getElementsByTagName("timestamp");
                        Element fileTimeElement = (Element) fileTimeList.item(0);
                        NodeList fileTime = fileTimeElement.getChildNodes();
                        Long timestamp = Long.parseLong(((Node) fileTime.item(0)).getNodeValue());
                        // hash path, timestamp
                        InfoFile info = new InfoFile();
                        info.timestamp = timestamp;
                        info.type = 1;
                        hashRepo.put(path, info);
                    }
                }
            }
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
        return hashRepo;
    }

    public void printHashFile(HashMap<String, InfoFile> hashFile) {
        for(String s: hashFile.keySet()) {
            int type = hashFile.get(s).type;
            Long timestamp = hashFile.get(s).timestamp;
            System.out.println(s + ": " + Integer.toString(type) + "; " + Long.toString(timestamp));
        }
    }

}
